/**
 * File:    ThinningAlgorithm.h
 * Author:  Bui Quang Anh
 * Email:   quang_anh.bui@univ-lr.fr
 * Version: 1.0
 * 
 * DESCRIPTION:
 * Header file for class ThinningAlgorithm.
 * Provide algorithms for image skeletonization and half skeletonization
 * 
 * CHANGE HISTORY:
 * (13/10/2011 13:17) File first time created - BUI Quang Anh
 * (14/10/2011 12:46) Implementation completed - revision 1 - BUI Quang Anh
 */

#pragma once

#include <iostream>
#include <cmath>
#include <vector>
#include <utility>
#include <sstream>
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>

class ThinningAlgorithm
{
public:
	/*----------- Properties -----------*/

	/*----------- Functions -----------*/
	
	// Find image's skeleton
	// @source: source image
	// @dest: destination image
	void thinning( const IplImage *source, IplImage *dest);

	// Find image's half-thinned skeleton
	// @source: source image
	// @dest: destination image
	void half_thinning(IplImage *source, IplImage *dest);

	// Constructor
	ThinningAlgorithm(void);
	// Destructor
	~ThinningAlgorithm(void);
	
private:
	/*----------- Properties -----------*/
	static unsigned char MASK[3][3];

	/*----------- Functions -----------*/
	
	/*---------------- Border removel conditions used for thinning algorithm ----------------*/
	
	/* 
	Mask pattern:
	                          x4  x3  x2
							  x5  p   x1
							  x6  x7  x8
	*/
	
	// Check first condition used for remove border pixel
	// B(p) = number of image pixels (black pixels) in 8-neighbours of p
	// First condition: 2 <= B(p) <= 6
	// @mask: mask pattern
	bool check_first_condition(unsigned char mask[3][3]);

	// Check second condition used for remove border pixel
	// Xr(p) = number of pattern [0,1] in chain x1, x2, x3, ... x8
	// Return Xr(p)
	// Second condition: Xr(p) == 2
	// @mask: mask pattern
	int check_second_condition(unsigned char mask[3][3]);

	// Check third condition used for remove border pixel
	// Third condition: x1 * x3 * x7 == 0
	// @mask: mask pattern
	bool check_third_condition(unsigned char mask[3][3]);

	// Check fourth condition used for remove border pixel
	// Fourth condition: x1 * x7 * x5 == 0
	// @mask: mask pattern
	bool check_fourth_condition(unsigned char mask[3][3]);

	// Check fifth condition used for remove border pixel
	// Fifth condition: x1 * x3 * x5 == 0
	// @mask: mask pattern
	bool check_fifth_condition(unsigned char mask[3][3]);

	// Check sixth condition used for remove border pixel
	// Sixth condition: x3 * x5 * x7 == 0
	// @mask: mask pattern
	bool check_sixth_condition(unsigned char mask[3][3]);

	// Check seventh condition used for remove border pixel
	// Seventh condition: One of these 2 conditions must satisfy:
	// a) (x1 * x7 == 1) and (x2 + x6 != 0) and (x3 + x4 + x5 + x8 == 0)
	// b) (x1 * x3 == 1) and (x4 + x8 != 0) and (x2 + x5 + x6 + x7 == 0)
	// @mask: mask pattern
	bool check_seventh_condition(unsigned char mask[3][3]);

	// Check eight condition used for remove border pixel
	// Eight condition: One of these 2 conditions must satisfy:
	// a) (x3 * x5 == 1) and (x4 + x8 != 0) and (x1 + x2 + x6 + x7 == 0)
	// b) (x5 * x7 == 1) and (x2 + x6 != 0) and (x1 + x3 + x4 + x8 == 0)
	// @mask: mask pattern
	bool check_eighth_condition(unsigned char mask[3][3]);

	// Kernel of thinning algorithm
	// Delete contour points that satisfy conditions
	// @source: source image
	// Output: Return true if source image is modified, else, return false
	bool thinning_kernel(IplImage* source);

};

